<?php

namespace fwkit;

class Collection extends \ArrayObject implements \JsonSerializable
{
    const ALPHA_ONLY = 11;

    private $_extraFlags = 0;

    private $_extraData = [];

    public function __construct(?array $data = [], int $flags = 0)
    {
        parent::__construct();
        // $this->setFlags(self::ARRAY_AS_PROPS);
        $this->_extraFlags = $flags;
        $data && $this->update($data);
    }

    public function __get(string $property)
    {
        return $this->offsetGet($property);
    }

    public function __set(string $property, $value)
    {
        $this->offsetSet($property, $value);
    }

    public function update(array $data)
    {
        foreach ($data as $key => $value) {
            $this->offsetSet($key, $value);
        }
    }

    public function offsetExists($index): bool
    {
        if (parent::offsetExists($index)) {
            return true;
        }

        $index = strval($index);
        if ($this->_extraFlags === self::ALPHA_ONLY) {
            $newIndex = \strtolower(\str_replace(['_', '-'], '', $index));
            return isset($this->_extraData[$index]) || isset($this->_extraData[$newIndex]);
        }

        return false;
    }

    public function offsetGet($index)
    {
        if (parent::offsetExists($index)) {
            return parent::offsetGet($index);
        }

        $index = strval($index);
        if ($this->_extraFlags === self::ALPHA_ONLY) {
            $newIndex = \strtolower(\str_replace(['_', '-'], '', $index));

            if (array_key_exists($index, $this->_extraData)) {
                return $this->_extraData[$index];
            } elseif (array_key_exists($newIndex, $this->_extraData)) {
                return $this->_extraData[$newIndex];
            }
        }

        return null;
    }

    public function offsetSet($index, $value)
    {
        if (is_array($value)) {
            $value = new self($value, $this->_extraFlags);
        }

        parent::offsetSet($index, $value);

        $index = strval($index);
        if ($this->_extraFlags === self::ALPHA_ONLY) {
            $newIndex = \strtolower(\str_replace(['_', '-'], '', $index));
            $this->_extraData[$newIndex] = $value;
        }
    }

    public function offsetUnset($index)
    {
        parent::offsetUnset($index);

        $index = strval($index);
        if ($this->_extraFlags === self::ALPHA_ONLY) {
            $newIndex = \strtolower(\str_replace(['_', '-'], '', $index));
            unset($this->_extraData[$newIndex]);
        }
    }

    public function toArray(): array
    {
        $data = [];
        foreach ($this as $key => $value) {
            if (is_object($value)) {
                if (method_exists($value, 'toArray')) {
                    $data[$key] = $value->toArray();
                } else {
                    $data[$key] = $value;
                }
            } else {
                $data[$key] = $value;
            }
        }

        return $data;
    }

    public function jsonSerialize()
    {
        return (array) $this;
    }
}
